تدعم البيرل ايضاً المراجع التي هي مشابهة بالمؤشرات والمراجع في السي ،مفهوم المراجع بسيط نسبياً في أغلب لغات البرمجة حيث تستخدم قطعة واحدة من البيانات في الذاكرة لكي تسترجع لنا بيانات اخرى قد يكون متغيراً او مصفوفة او هاش ،تسمى هذة القطعة بالمؤشر في لغات البرمجه مثل (Pascal أو C) واحياناً تسمى indirect referencing مثل للغة التجميع assembly ، في بعض اللغات لايتم توضيح مفهوم المؤاشرات كالـ (BASIC أو Java) وفي البيرل فاالمؤشرات تسمى بالمراجع ، ولانشاء مرجع لمتغير موجود اوقيمة يتم عمل ذلك بواسطة وضع " \ " في المقدمة والشكل التالي يوضح مختلف المراجع المستخدمة

لإنشاء مرجع الى المتغير الذي يسمى $slr_ref نقوم بتخصيص
$s="cargo"; # A normal scalar $slr_ref=\$s; # Create a reference to $s
يمكن ان يمثل كما في الشكل التالي

لايحتوي المتغير $slr_ref على بيانات عند العرض ،SCALAR(0x8060194) بل عنوان المتغير $s ، ولكي نحصل على قيمة المتغير $s من خلال المتغير $slr_ref يجب ان نقوم بعمل dereferenceوذلك من خلال وضع اشارة $ امام المرجع .
print $$slr_ref;
او نستطيع الفصل بعلامات ${...} التي تقوم بنفس العمل
print ${$slr_ref};
ويمكنك تعديل القيمة الاصلية للمتغير $s
$$slr_ref="Sticks"; # De-references $$slr_ref
الان اصبح بعد التعديل

واذا استعملت $slr_ref بدلاً من $$slr_ref يستبدل محتوى المتغير $slr_ref وليس مايشير اليه
$slr_ref="Break";
يصبح

عند تخصيص موقع الى متغير اخر ذلك يعني نسخ الموقع الى ذلك المتغير ويصبح كليهما بنفس العنوان
$name="Ganda"; $nref=\$name; # Has a reference to $name $oref=$nref; # Has a copy of the reference
$$oref و $$nref كليهما يعطينا القيمة "Ganda"

ايضاً يمكن تخزين مرجع الى المرجع reference to a reference
$book="Lord of the Rings"; $bref=\$book; # A reference to $book $bref2=\$bref; # A reference to $bref (not to $book!)
يمكن تمثل ذلك كما في الشكل

بنفس طريقة انشاء مرجع الى متغير
@arr = ('this','is','an','array','mine');
$aref=\@arr;

للوصول الى هذة المصفوفة من خلال $aref ،نستطيع الوصول الى جزء او عدة اجزاء او الى المصفوفة كاملة
$value = $$aref[0]; # الوصول الى اول عنصر من المصفوفة @slice = @$aref[2,3]; # الوصول الى قطعة من المصفوفة @array = @$aref; # الوصول الى المصفوفة كاملاً
نستطيع فصل المرجع بواسطة علامات الحصر
$$aref[0] نفس ${$aref}[0] نفس $aref->[0]
@$aref[2,3] نفس @{$aref}[2,3]
@$aref نفس @{$aref}
فمثلاً عند الرغبة لطباعة عناصر المصفوفة :
foreach $element (@{$aref}) {
print $element;
}
لإنشاء مرجع الى الهاش
%hash = (cat => "meow", dog => "woof", goldfish => undef); $href = \%hash; # reference to a hash
امكانية الوصول الى هذة الهاش بواسطة المرجع يمكننا الوصول الى جزء او عدة اجزاء او يمكن الوصول الى الهاش كاملاً وهنا جميع حالات الوصول
%c = %$href; # وصول كاملُ
$value = $href->{$key}; # الحصول على القيمة بالفهرس المحدد
$arr[0] = ${$href}{dog}; # غير واضح : $arr[0] = $hash{dog}
$arr[0] = $href->{dog}; # اوضح : $arr[0] = $hash{dog}
# او بنفس التخصيص باستعمال مرجع المصفوفة
${$aref}[0] = $hash{dog};# غير واضح : $arr[0] = $hash{dog}
$aref->[0] = $hash{dog}; # اوضح : $arr[0] = $hash{dog}
@slice = @$href{$key1, $key2, $key3}; # الحصول على عديد قيم!
@keys = keys %$href; # الحصول على الفهارس
@values = values %$href; # الحصول على القيم
ايضاً يمكن ان تكون المتغيرات مخفية ولايوجد أسم يشير الية وللوصل الى هذة القيم فقط بواسطة نفس dereference السابق ، والتالي جميع الحالات مجتمعه معاً:
| النوع | تخصيص المرجع الى متغير | تخصيص المرجع الى متغير مخفي |
|---|---|---|
| scalar | $ref = \$scalar | $ref = \"scalar" |
| list | $ref = \@arr | $ref = [ 1, 2, 3 ] |
| hash | $ref = \%hash | $ref = { a=>1, b=>2, c=>3 } |
| subroutine | $ref = \&subr | $ref = sub { print "hello, world\n" } |
كما سبق يمكن للمصفوفة ان تأخذ مرجعاً
$arrayref = \@array;
ويمكننا ايضاً ان نقوم بنسخ المصفوفة وتخصيصها الى المرجع بواسطة استخدام الـقوس array reference constructor [...] ( يعرف ايضاً بالـanonymous array constructor
$copyofarray = [@array];
فكلتا الطريقتين تعطينا المرجع الى مصفوفة مخفية التي يمكننا ان نخصص اليها ، الفرق بين الطرقتين الاول ينتج المرجع الذي سيشير الى المصفوفة الاصلية ولذا يمكن ان تستعمل للمرور الى subroutines للمعالجة البيانات الاصلية لها ، بينما الاخر سوف ينشاء نسخة من المصفوفة التي يمكن ان تعدل بشكل منفصل
#!/usr/bin/perl -w
sub n_subr {
$$ref[0]="e";
}
@a=("a","b","c","d");
$ref=[@a];
#$ref=\@a;
print "before :$ref->[0]\t$a[0]\n";
n_subr();
print "after :$ref->[0]\t$a[0]\n";
لانشاء مرجع الى هاش
%hash=( Mouse => 'Jerry',Cat=>'tom',Dog=>'spike');
$hashref=\%hash;
$dog=$hashref->{Dog}; #or $dog=$$hashref{Dog}
ايضاً لإنشاء مرجع هاش(مرجع الى الهاش المخفي) مع {...} constructor ، الذي سوف ينشئ brand جديد لهاش مخفي وبنفس محتوى السابق
$hashref={ Mouse => 'Jerry',Cat=>'tom',Dog=>'spike'};
$dog=$hashref->{Dog};
فالاختلاف اننا لانستطيع عمل مرجع المصفوفة مع constructor, [...] بسبب ان المرجع يشير الى هاش مخفي
بهذة الطريقة يمكن ان ننشئ مايسمى بالـسجل (record) ويستعمل بكثره في البرامج وهو مفيد لتضمين مختلف الانواع من البيانات ، في لغه السي هو نوع البيانات struct
$record = {
NAME => "Jason",
EMPNO => 132,
TITLE => "deputy peon",
AGE => 23,
SALARY => 37_000,
PALS => [ "Norbert", "Rhys", "Phineas"],
};
printf "I am %s, and my pals are %s.\n",
$record->{NAME},
join(", ", @{$record->{PALS}});
foreach $i (keys %$record)
{
print $i,"\t",$record->{$i},"\n";
}
ويمكننا ايضاً انشاء مرجع الى هاش مخفي بمحتوى مصفوفة ،وكذلك يمكننا انشاء مرجع الى مصفوفة مخفية بمحتوى هاش كالتالي :
$hashref = {@array};
$arrayref = [%hash];
ويمكن ان نعلان عن مرجع وقيمة ابتدائية فارغة مع [] and {}
my $arrayref=[]; # reference to empty array
my $hashref={}; # reference to empty hash
ومن الاخطاء الشائعة وجود \ امامة .توفر البيرل امكانية معرفة مسبقة لنوع المرجع بواسطة الدالة ref ، فكل مانحتاجة تضمين المراجع الى هذة الدالة ، اذا تركت بدون وسيط تأخذ الدالة المتغير الخاص $_ كوسيط
$ref = \[1, 2, 3]; print "The reference type of $ref is '", ref($ref),"' \n"; #output: The reference type of ARRAY(0x8250290) is 'ARRAY'
فنلاحظ ان مفسر البيرل لايستطيع اداء عمليات المراقبة للصيغة الصحيحة لضمان المراجع بسبب ان محتوي المتغير يعرف في وقت التشيغل ويمكن تغيرة اثناء تنفيذ البرنامج
# Declare reference to (empty) anonymous array
$array = [ ];
# Initialize the array
for($i=0; $i < 4 ; ++$i) {
for($j=0; $j < 4 ; ++$j) {
$array->[$i][$j] = $i * $j;
}
}
# Reset one of the elements of the array
$array->[3][2] = 99;
# Print the array
for($i=0; $i < 4 ; ++$i) {
for($j=0; $j < 4 ; ++$j) {
printf("%3d ", $array->[$i][$j]);
}
print "\n";
}
دالة ref يمكن ان تعيد احد القيم التالية :
| القيمة | المعنى |
|---|---|
| SCALAR | A scalar reference |
| ARRAY | An array reference |
| HASH | A hash reference |
| CODE | A reference to an anonymous subroutine |
| GLOB | A reference to a typeglob |
| IO (or IO::Handle) | A filehandle reference |
| REF | A reference to another reference |
| LVALUE | A reference to an assignable value that isn’t a SCALAR, ARRAY, or HASH (e.g., the return value from substr) |
| "Regexp" | a reference to a precompiled pattern |
لعلاء مرجع الدالة و الدالة المخفية يشيران الى نفس الاسم الفرق الوحيد ان الدالة المخفية لاتأخذ اسماً ،عنوان الدالة المخفية تخزن الى متغير ( او عنصر من مصفوفة او قيمة هاش ) ثم يمكننا الوصول الى الدالة من خلال هذا المتغير . التالي تعريف دالة مخفية ودالة mysubroutine الى مرجع الدالة $subref
sub mysubroutine { print "Hello my subroutine"; }
my $subref = sub { print "Hello anonymous subroutine"; };
my $subref = \&mysubroutine;
الان لكي نستدعي هذة الدالة لدينا اكثر من طريقة ، اما بإستخدام علامة & التي تأمر البيرل باستداعى الدالة التي راجعه اليها ، وتعيد ناتج الاستدعاء .
# call an anonymous subroutine
&$subref; #or &{$subref}();
&$subref("a parameter"); #or &{$subref}("a parameter");
او يمكن القول بشكل أوضح التالي :
$subref->();
$subref->("a parameter");
ليست متقاربه الطريقتين ، فالاوله &$subref يمرر المصفوفة الحالية @_ (اذا كان يوجد باراميتر) مباشراً الى الدالة ، الشيء الاخر ان علامة & تجاهل prototype كما ذكرنا سابقاً، اما أستخدام المؤثر -> سيبقي prototype على وضعه ويفحص في وقت التجميع.
على سبيل المثال وضع مراجع للدوال في الهاش
sub skipper_greets {
my $person = shift;
print "Skipper: Hey there, $person!\n";
}
sub gilligan_greets {
my $person = shift;
print "Gilligan: Hi, $person!\n";
}
sub professor_greets {
my $person = shift;
print "Professor: By my calculations, you must be $person!\n";
}
my %greets = (
Gilligan => \&gilligan_greets,
Skipper => \&skipper_greets,
Professor => \&professor_greets,
);
for my $person (qw(Skipper Gilligan)) {
$greets{$person}->('Professor');
}
Skipper: Hey there, Professor! Gilligan: Hi, Professor!
وبنفس المثال بإستخدام الدالة المخفية
my %greets = (
Gilligan => sub {
my $person = shift;
print "Gilligan: Hi, $person!\n";
},
Skipper => sub {
my $person = shift;
print "Skipper: Hey there, $person!\n";
},
Professor => sub {
my $person = shift;
print "Professor: By my calculations, you must be $person!\n";
},
);
for my $person (qw(Skipper Gilligan)) {
$greets{$person}->('Professor');
}
فعند تضمين دالة فرعية مخفية (او مرجع دالة ) للدالة ، لايمكن الوصول اليها بواسطة المرجع الا من تلك الدالة بسبب ان المرجع هو متغير محلى للدالة ، لذا الدالة الفرعية المخفية اكثر اخفاء للبيانات عن البرنامج الرئيسي .
sub performCalc {
my ($firstVar, $secondVar) = @_;
my $square = sub {
return($_[0] ** 2);
};
return(&$square($firstVar) + &$square($secondVar));
};
$temp = performCalc(10, 10);
print("temp = $temp\n");
temp = 200
باستعمال معامل \& هو مفيد اكثر بسبب يمكن ان نمرر مرجع كالباراميتر ويسمح بامرار مرجع الى متغير او الى مصفوفة او هاش او دالة اخرى، فعلى سبيل المثال لمرار مصفوفتين ودمجها معاًُ باستعمال الدوال سيكون
mysub (@array1, @array2);
sub mysub {
my @combinedarray = @_;
foreach (@combinedarray) {
...
}
واذا اردت عدم دمج المصفوفتين فالحل امرار مراجع مصفوفة
mysub (\@array1, \@array2);
sub mysub {
my ($arrayref1, $arrayref2) = @_;
foreach (@$arrayref1) {
print "$_ ... ";
}
foreach (@$arrayref2) {
print "$_ ... ";
}
}
واذا اردت امرار مرجع الى دالة اخرى على سبيل المثال
#!/usr/bin/perl
# callsub.pl
use warnings;
use strict;
sub do_list {
my ($subref, @in) = @_;
return map { &$subref ($_) } @in;
}
sub add_one {
return $_[0] + 1;
}
$, = ",";
print do_list (\&add_one, 1, 2, 3); # prints 2, 3, 4